#pragma once
#include <string>
#include "DateStringMap.h"
#include "TinyStringMap.h"
#include "PackedString.h"
#include "AssignBuffer.h"

enum kOptimizeType{
	kOptimizeTypeNone,				//
	kOptimizeTypeTinyMap,			//
	kOptimizeTypeDate,				//
	kOptimizeTypePackedString,		//
	kOptimizeTypePackedSizeString,	//
	kOptimizeTypeMappedSizeString,	//
	kOptimizeTypeCount				// 
};
enum FieldAccessMode{
	FieldModeBytes,
	FieldModeSharedBytes,
	FieldModeCategory,
	FieldModeName,
	FieldModeType,
	FieldModeSync,
};
// 不优化版本的字段成员,TYPE只能是char[],或者string
template<typename TYPE, typename STORAGE, kOptimizeType OPTIMIZE = kOptimizeTypeNone>
class ClassMember{
	typedef ClassMember<TYPE, STORAGE, kOptimizeTypeNone> ThisType;
	TYPE			m_data;
public:
	ClassMember(){ AssignBuffer<TYPE>(m_data, "", 0); }
	void Reset(){ AssignBuffer<TYPE>(m_data, "", 0); }
	inline operator const char*()const{ return GetBufferPtr<TYPE>(m_data); }
	inline const char* Read()const{ return GetBufferPtr<TYPE>(m_data); }
	bool operator==(const ThisType& t)const{ 
		return IsTypeDataEqual<TYPE>(m_data, t.m_data);
	}
	bool operator!=(const ThisType& t)const{ 
		return !IsTypeDataEqual<TYPE>(m_data, t.m_data);
	}
	void operator=(const char* str){ AssignBuffer<TYPE>(m_data, str, str?strlen(str):0); }
	void Write(const char* str, int len){ AssignBuffer<TYPE>(m_data, str, len); }
	int Category()const{ return 0; }
	int TypeEncoding()const{ return GetTypeEncoding<TYPE>(); }
	int GetDirectMemSize()const{ return sizeof(*this); }
	int GetSharedMemSize()const{ return 0; }
};

// 当OPTIMIZE为kOptimizeTypeTinyMap的偏特化,要求STORAGE必须是TinyStringMap
template<typename TYPE, typename STORAGE>
class ClassMember<TYPE, STORAGE,kOptimizeTypeTinyMap>{
	typedef ClassMember<TYPE, STORAGE, kOptimizeTypeTinyMap> ThisType;
	unsigned short	m_id;
public:
	ClassMember(){ m_id = 0; }
	ThisType& operator=(const ThisType& m){ m_id = m.m_id; return *this; }
	bool operator==(const ThisType& t)const{ 
		return m_id == t.m_id; 
	}
	bool operator!=(const ThisType& t)const{ 
		return m_id != t.m_id;
	}
	void Reset(){ m_id = 0; }
	inline operator const char*()const{ return STORAGE::Get().Load(m_id); }
	const char* Read()const{ return STORAGE::Get().Load(m_id); }
	void operator=(const char* str){ Write(str, str ? strlen(str) : 0); }
	void Write(const char* str, int len){ m_id = STORAGE::Get().Save(str, len); }
	int Category()const{ return STORAGE::Get().Category(); }
	int TypeEncoding()const{ return GetTypeEncoding<TYPE>(); }
	int GetDirectMemSize()const{ return sizeof(*this); }
	int GetSharedMemSize()const{ return STORAGE::Get().Memory(); }
};

// 当OPTIMIZE为kOptimizeTypeDate的偏特化,要求STORAGE必须是DateStringMap
template<typename TYPE, typename STORAGE>
class ClassMember<TYPE, STORAGE,kOptimizeTypeDate>{
	typedef ClassMember<TYPE, STORAGE, kOptimizeTypeDate> ThisType;
	typedef typename STORAGE::DateType DateType;
	DateType	m_id;
public:
	ClassMember(){ m_id = 0; }
	void Reset(){ m_id = 0; }
	bool operator==(const ThisType& t)const{
		return m_id == t.m_id; 
	}
	bool operator!=(const ThisType& t)const{ 
		return m_id != t.m_id; 
	}
	ThisType& operator=(const ThisType& m){ m_id = m.m_id; return *this; }
	inline operator const char*()const{ return STORAGE::Get().Load(m_id); }
	const char* Read()const{ return STORAGE::Get().Load(m_id); }
	void operator=(const char* str){ Write(str, str ? strlen(str) : 0); }
	void Write(const char* str, int len){ m_id = STORAGE::Get().Save(str, len); }
	int Category()const{ return STORAGE::Get().Category(); }
	int TypeEncoding()const{ return GetTypeEncoding<TYPE>(); }
	int GetDirectMemSize()const{ return sizeof(*this); }
	int GetSharedMemSize()const{ return STORAGE::Get().Memory(); }
};

// 当OPTIMIZE为kOptimizeTypePackedString的偏特化,要求STORAGE必须是PackedString
// PackedString只有一个指针成员,无长度信息,长度需要通过strlen来实时计算
template<typename TYPE, typename STORAGE>
class ClassMember<TYPE, STORAGE,  kOptimizeTypePackedString>{
	typedef ClassMember<TYPE, STORAGE, kOptimizeTypePackedString> ThisType;
	STORAGE			m_storage;
public:
	ClassMember(){}
	void Reset(){ m_storage.reset(); }
	inline operator const char*()const{ return m_storage.c_str(); }
	const char* Read()const{ return m_storage.c_str(); }
	bool operator==(const ThisType& t)const{
		return m_storage == t.m_storage;
	}
	bool operator!=(const ThisType& t)const{ 
		return m_storage != t.m_storage; 
	}
	void operator=(const char* str){ m_storage.asign(str, str ? strlen(str) : 0); }
	void Write(const char* str, int len){ m_storage.asign(str, len); }
	int Category()const{ return m_storage.Category(); }
	int TypeEncoding()const{ return GetTypeEncoding<TYPE>(); }
	int GetDirectMemSize()const{ return m_storage.size() + sizeof(*this); }
	int GetSharedMemSize()const{ return 0; }
};

template<typename TYPE, typename STORAGE>
class ClassMember<TYPE, STORAGE, kOptimizeTypeMappedSizeString>{
	typedef ClassMember<TYPE, STORAGE, kOptimizeTypeMappedSizeString> ThisType;
	STORAGE			m_storage;
public:
	ClassMember(){}
	void Reset(){ m_storage.reset(); }
	inline operator const char*()const{ return m_storage.c_str(); }
	const char* Read()const{ return m_storage.c_str(); }
	void Load(std::string& str)const{ m_storage.Load(str); }
	bool operator==(const ThisType& t)const{ 
		return m_storage == t.m_storage; 
	}
	bool operator!=(const ThisType& t)const{ 
		return m_storage != t.m_storage;
	}
	void operator=(const char* str){ m_storage.asign(str, str ? strlen(str) : 0); }
	void Write(const char* str, int len){ m_storage.asign(str, len); }
	int Category()const{ return m_storage.Category(); }
	int TypeEncoding()const{ return GetTypeEncoding<TYPE>(); }
	int GetDirectMemSize()const{ return sizeof(*this); }
	int GetSharedMemSize()const{ return m_storage.shared_memory(); }
};
//
//
//template<typename TYPE, typename STORAGE, bool OPTIMIZE = false>
//class BondField{
//	TYPE			m_data;
//public:
//	BondField(){ AssignBuffer<TYPE>(m_data, "", 0); }
//	const char* Read(){return GetBufferPtr<TYPE>(m_data);}
//	void Write(const char* str, int len){AssignBuffer<TYPE>(m_data, str, len);}
//	int StorageBytes()const{ return sizeof(*this); }
//	int Category()const{ return STORAGE::Get().Category(); }
//};
//
//template<typename TYPE, typename STORAGE>
//class BondField<TYPE, STORAGE, true>{
//	unsigned short	m_id;
//public:
//	BondField(){ m_id = 0; }
//	const char* Read(){ return STORAGE::Get().Load(m_id); }
//	void Write(const char* str, int len){ m_id = STORAGE::Get().Save(str, len); }
//	int StorageBytes()const{ return STORAGE::Get().Memory() + sizeof(*this); }
//	int Category()const{ return STORAGE::Get().Category(); }
//};
//
//
//template<typename TYPE, typename STORAGE, bool OPTIMIZE = false>
//class BondDateField{
//	TYPE			m_data;
//public:
//	const char* Read(){return GetBufferPtr<TYPE>(m_data);}
//	void Write(const char* str, int len){AssignBuffer<TYPE>(m_data, str, len);}
//	int StorageBytes()const{ return sizeof(*this); }
//	int Category()const{ return STORAGE::Get().Category(); }
//};
//template<typename TYPE, typename STORAGE>
//class BondDateField<TYPE, STORAGE, true>{
//	unsigned int	m_id;
//public:
//	const char* Read(){return STORAGE::Get().Load(m_id);}
//	void Write(const char* str, int len){m_id = STORAGE::Get().Save(str, len);}
//	int StorageBytes()const{return STORAGE::Get().Memory() + sizeof(*this);}
//	int Category()const{ return STORAGE::Get().Category(); }
//};
//
//template<typename TYPE, typename STORAGE,bool OPTIMIZE=false>
//class BondStringField{
//	TYPE			m_data;
//public:
//	const char* Read(){ return GetBufferPtr<TYPE>(m_data); }
//	void Write(const char* str, int len){ AssignBuffer<TYPE>(m_data, str, len); }
//	int StorageBytes()const{ return sizeof(*this); }
//	int Category()const{ return 0; }
//};
//
//template<typename TYPE, typename STORAGE>
//class BondStringField<TYPE, STORAGE,true>{
//	STORAGE			m_storage;
//public:
//	const char* Read(){return m_storage.c_str();}
//	void Write(const char* str, int len){m_storage.asign(str, len);}
//	int StorageBytes()const{return m_storage.size() + sizeof(*this);}
//	int Category()const{ return m_storage.Category(); }
//};

struct FieldInfo {
	std::string		name;
	int			offset;
	int			size;
	int			index;
	int			gap;
};

struct FieldStat{
	int		field_offset;		// 字段偏移量
	int		field_size;			// 原始字段长度
	int		value_count;		// 取值个数
	int		avg_length;			// 平均长度
	int		max_length;			// 最大长度
	int		real_bytes;			// 真实内存
	int		valid_bytes;		// 理论节省
	int		actual_bytes;		// 实际节省
	int		opti_bytes;			// 优化后的字节数
	float	use_ratio;			// 内存使用效率
	FieldStat()
	{
		memset(this, 0, sizeof(FieldStat));
	}
	FieldStat(int offset, int size, int vcount, int avglen, int maxlen, int rbytes, int vbytes, int abytes, float ratio) :
		field_offset(offset), field_size(size), value_count(vcount), avg_length(avglen), max_length(maxlen), real_bytes(rbytes),
		valid_bytes(vbytes), actual_bytes(abytes), opti_bytes(0), use_ratio(ratio){}
};

class CBondInfoBitFlag {
	typedef unsigned char uchar;
	bool			m_nIsQuotTopflag : 1;					//是否置顶,			编码: true:置顶	false:不置顶
	bool			m_bIsValid : 1;							//true表示有效债券，否则为无效债券
	bool			m_bExpireInHoliday : 1;					//到期日是否节假日，ture：节假日
	uchar			m_sMortgage : 2;						//可质押				编码："Y"
	uchar			m_sCrossmarket : 2;						//跨市场				编码："Y","N"
	uchar			m_sIsMunicipal : 2;						//城投					编码："Y"
public:
	inline char decode(uchar member)const//to y/n/\0
	{
		if (member < 0 || member >= 2)return '\0';
		return member == 0 ? 'N' : 'Y';
	}
	inline uchar encode(char raw)const// from y/n/\0
	{
		if ('N' == raw || 'n' == raw)return 0;
		if ('Y' == raw || 'y' == raw)return 1;
		return 2;
	}
public:
	CBondInfoBitFlag(unsigned short v) {
		static_assert(sizeof(unsigned short) == sizeof(CBondInfoBitFlag), "sizeof(unsigned short) != sizeof(CBondInfoBitFlag)");
		*((unsigned short*)this) = v;
	}
	CBondInfoBitFlag() :m_nIsQuotTopflag(false), m_bIsValid(false), m_bExpireInHoliday(false), m_sMortgage(), m_sCrossmarket(), m_sIsMunicipal() {}
	bool operator==(const CBondInfoBitFlag& flag)const {
		return m_nIsQuotTopflag == flag.m_nIsQuotTopflag &&
			m_bIsValid == flag.m_bIsValid &&
			m_bExpireInHoliday == flag.m_bExpireInHoliday &&
			m_sMortgage == flag.m_sMortgage &&
			m_sCrossmarket == flag.m_sCrossmarket &&
			m_sIsMunicipal == flag.m_sIsMunicipal;
	}
	bool operator!=(const CBondInfoBitFlag& flag)const {
		return !(this->operator==(flag));
	}
	inline void SetStickFlag(int tp) { m_nIsQuotTopflag = tp != 0 ? true : false; }
	inline void SetValidFlag(bool valid) { m_bIsValid = valid; }
	inline void SetExpireInHoliday(bool bHoliday) { m_bExpireInHoliday = bHoliday; }
	inline void SetMortgageFlag(char sMortgage) { m_sMortgage = encode(sMortgage); }
	inline void SetCrossmarketFlag(char sCrossmarket) { m_sCrossmarket = encode(sCrossmarket); }
	inline void SetMunicipalFlag(char sMunicipal) { m_sIsMunicipal = encode(sMunicipal); }
	inline bool GetStickFlag()const { return m_nIsQuotTopflag; };
	inline bool GetValidFlag()const { return m_bIsValid; };
	inline bool GetExpireInHoliday()const { return m_bExpireInHoliday; };
	inline char GetMortgageFlag()const { return decode(m_sMortgage); };
	inline char GetCrossmarketFlag()const { return decode(m_sCrossmarket); };
	inline char GetMunicipalFlag()const { return decode(m_sIsMunicipal); };
public://方便快捷的接口
	inline bool	GetQuotTopflag() { return GetStickFlag(); }
	inline bool	IsMortgage()const { return ('Y' == GetMortgageFlag() || 'y' == GetMortgageFlag()); }
	inline bool	IsCrossMarket()const { return ('Y' == GetCrossmarketFlag() || 'y' == GetCrossmarketFlag()); }
	inline bool	IsMunicipal()const { return ('Y' == GetMunicipalFlag() || 'y' == GetMunicipalFlag()); }
	inline bool IsValidBond() const { return GetValidFlag(); }
	inline bool IsExpireInHoliday()const { return GetExpireInHoliday(); }
	inline int GetIsQuotTopflag() const { return GetStickFlag() ? 1 : 0; }
	inline char GetMortgage() const { return GetMortgageFlag(); }
	inline char GetIsMunicipal() const { return GetMunicipalFlag(); }
	inline char GetCrossmarket() const { return GetCrossmarketFlag(); }
};
